package tree

import "fmt"

func doFunc[R comparable](node *Node[R]) {
	if node != nil {
		fmt.Println(node.Value)
	}
}

func PreOrder[R comparable](root *Node[R]) {
	if root == nil {
		return
	}
	doFunc(root)
	PreOrder(root.Left)
	PreOrder(root.Right)
}

func inOrder[R comparable](root *Node[R]) {
	if root == nil {
		return
	}
	inOrder(root.Left)
	doFunc(root)
	inOrder(root.Right)
}

func postOrder[R comparable](root *Node[R]) {
	if root == nil {
		return
	}

	inOrder(root.Left)
	inOrder(root.Right)
	doFunc(root)
}

func levelOrder[R comparable](root *Node[R]) {
	queue := make([]*Node[R], 0)
	queue = append(queue, root)
	for i := 0; i < len(queue); i++ {
		node := queue[i]
		doFunc(node)
		if node.Left != nil {
			queue = append(queue, node.Left)
		}

		if node.Right != nil {
			queue = append(queue, node.Right)
		}
	}
}

func Hash(v interface{}) uint32 {
	switch t := v.(type) {
	case string:
		return hashString(t)
	case int32:
		return uint32(t)
	case uint32:
		return t
	case int:
		return uint32(t)
	default:
		return 0
	}
}

func hashString(s string) uint32 {
	h := int32(0)
	length := len(s)
	for i := 0; i < length; i++ {
		h = 31*h + int32(s[i])
	}
	return uint32(h)
}
